package com.freewater.library.lending.reader.infrastructure.po;

import com.freewater.library.lending.reader.infrastructure.model.ReaderImpl;
import com.freewater.library.lending.reader.model.Reader;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.Set;
import java.util.stream.Collectors;

@Table(name = "reader")
@Entity
@Getter
@Setter
@NoArgsConstructor
public class ReaderPo {
    /**
     * 读者Id
     */
    @Id
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 是否已被暂停借阅
     */
    private boolean suspended;
    /**
     * 占用的书
     */
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "readerId", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<OccupiedBookPo> occupiedBooks;
    /**
     * 逾期的书
     */
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "readerId", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<CheckedOutOverduePo> checkedOutOverdueBooks;
    /**
     * 乐观锁
     */
    @Version
    private int version;

    public ReaderPo(Reader reader) {
        this.id = reader.getId();
        this.name = reader.getName();
        this.suspended = reader.isSuspended();
        this.occupiedBooks = reader.getOccupiedBooks().stream()
                .map(book -> new OccupiedBookPo(reader.getId(), book))
                .collect(Collectors.toSet());
        this.checkedOutOverdueBooks = reader.getCheckedOutOverdueBooks().stream()
                .map(book -> new CheckedOutOverduePo(reader.getId(), book))
                .collect(Collectors.toSet());
        if (reader instanceof ReaderImpl readerImpl) {
            this.version = readerImpl.getVersion();
        } else {
            this.version = 0;
        }
    }

    public static Reader convert(ReaderPo record) {
        ReaderImpl reader = new ReaderImpl(record.getId(),
                record.getName(),
                record.isSuspended(),
                record.getOccupiedBooks().stream()
                        .map(OccupiedBookPo::convert)
                        .collect(Collectors.toSet()),
                record.getCheckedOutOverdueBooks().stream()
                        .map(CheckedOutOverduePo::convert)
                        .collect(Collectors.toSet())
        );
        reader.setVersion(reader.getVersion());
        return reader;
    }
}
